import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Menu } from "./entities/menu.entity";
import { FindCondition, Repository, Like, In } from "typeorm";
import { SharedService } from "src/shared/shared.service";
import { MenuTree, Router } from "./dto/res-menu.dto";
import { ReqAddMenuDto, ReqSearchDto, ReqUpdateMenu } from "./dto/req-menu.dto";
import { Role } from "../role/entities/role.entity";

@Injectable()
export class MenuService {
  constructor(
    @InjectRepository(Menu) private readonly menuRepository: Repository<Menu>,
    private readonly sharedService: SharedService,
  ) {}

  // 新增/编辑
  async addOrUpdate(reqAddMenuDto: ReqAddMenuDto) {
    if (reqAddMenuDto.parentId) {
      const parentMenu = await this.findById(reqAddMenuDto.parentId);
      reqAddMenuDto.parent = parentMenu;
    }
    await this.menuRepository.save(reqAddMenuDto);
  }

  // 通过id查询
  async findById(menu_id: number | string) {
    return this.menuRepository.findOne(menu_id);
  }

  /**
   * @description: 根据角色查询 菜单列表
   * @param {boolean} isAdmin
   * @param {number} roleIdArr
   * @return {*}
   */
  async getMenuList(isAdmin: boolean, roleIdArr: number[]): Promise<Router[]> {
    const queryBuilder = this.menuRepository
      .createQueryBuilder("menu")
      .select("menu.menu_id", "menu_id")
      .addSelect("menu.menu_name", "menu_name")
      .addSelect("menu.order_num", "order_num")
      .addSelect("menu.icon", "icon")
      .addSelect("menu.component", "component")
      // .addSelect("menu.menu_type", "menu_type")
      .addSelect("menu.is_frame", "is_frame")
      .addSelect("menu.is_keepAlive", "is_keepAlive")
      .addSelect("menu.is_full", "is_full")
      .addSelect("menu.path", "path")
      .addSelect("menu.is_hide", "is_hide")
      .addSelect("menu.query", "query")
      .addSelect("ifnull(menu.parentMenuId,0)", "parentId");
    // .andWhere("menu.menu_type in ('M' , 'C')");
    // .andWhere((qb) => {
    //   const subQuery = qb
    //     .subQuery()
    //     .select("menu2.menu_id")
    //     .from(Menu, "menu2")
    //     .where("concat('.',menu.mpath) like concat('%.',menu2.menu_id,'.%')")
    //     .getQuery();
    //   return "not exists" + subQuery;
    // });
    // 关联角色查询
    if (roleIdArr) {
      queryBuilder
        .innerJoin("menu.roles", "role", "role.delFlag = 0")
        .andWhere("role.role_id IN (:...roleIdArr)", {
          roleIdArr,
        });
    }
    const menuList: ReqUpdateMenu[] = await queryBuilder
      .groupBy("menu.menu_id")
      .orderBy("menu.order_num")
      .getRawMany();
    const menuTreeList = [];
    this.sharedService.handleTree(menuList, "menu_id").forEach((item) => {
      menuTreeList.push(item);
      // if (item.menu_type == "C") {
      //   menuTreeList.push(item);
      // }
    });
    return this.createRouterTree(menuTreeList);
  }

  /**
   * @description: 生成菜单树
   * @param {Menu} menuArr
   * @return {*}
   */
  createRouterTree(menuArr: Menu[]): Router[] {
    const routerList: Router[] = [];
    menuArr.forEach((item) => {
      const router = new Router();
      router.name = item.name;
      router.component = item.component;
      // if (item.menu_type == "M" && item.is_frame == 1) {
      //   router.redirect = "noRedirect";
      // }
      // if (item.menu_type == "M") {
      // } else {
      //   console.log("item: ", item);
      //   router.component = item.component;
      // }

      router.path = item.path;
      router.meta = {
        title: item.menu_name,
        icon: item.icon,
        isLink: item.is_frame == 0 ? item.link_url : null,
        isKeepAlive: item.is_keepAlive == 0 ? false : true,
        isFull: item.is_full == 0 ? false : true,
        isHide: item.is_hide == 0 ? false : true,
      };
      if (item.children && item.children.length) {
        router.children = this.createRouterTree(item.children);
      }
      routerList.push(router);
    });
    return routerList;
  }

  /**
   * @description: 查询菜单列表
   * @return {*}
   */
  async list(reqSearchDto: ReqSearchDto) {
    const where: FindCondition<any> = {};
    if (reqSearchDto.menu_name) {
      where.menu_name = Like(`%${reqSearchDto.menu_name}%`);
    }
    if (reqSearchDto.name) {
      where.name = Like(`%${reqSearchDto.name}%`);
    }
    if (reqSearchDto.path) {
      where.path = Like(`%${reqSearchDto.path}%`);
    }
    if (reqSearchDto.component) {
      where.component = Like(`%${reqSearchDto.component}%`);
    }
    const menuList = await this.menuRepository
      .createQueryBuilder("menu")
      .select("menu.menu_id", "menu_id")
      .addSelect("menu.menu_name", "menu_name")
      .addSelect("menu.name", "name")
      .addSelect("menu.order_num", "order_num")
      .addSelect("menu.icon", "icon")
      .addSelect("menu.component", "component")
      .addSelect("menu.path", "path")
      // .addSelect("menu.menu_type", "menu_type")
      .addSelect("menu.is_frame", "is_frame")
      .addSelect("menu.is_keepAlive", "is_keepAlive")
      .addSelect("menu.is_full", "is_full")
      .addSelect("menu.is_hide", "is_hide")
      .addSelect("menu.link_url", "link_url")
      .addSelect("ifnull(menu.parentMenuId,0)", "parentId")
      .orderBy("menu.order_num", "ASC")
      .where(where)
      .getRawMany();

    const menuTreeList = [];
    this.sharedService.handleTree(menuList, "menu_id").forEach((item) => {
      menuTreeList.push(item);
      // if (item.menu_type == "C") {
      //   menuTreeList.push(item);
      // }
    });
    return menuTreeList;
  }

  /**
   * @description: 获取菜单下拉树
   * @return {*}
   */
  async getMenuTree() {
    const queryBuilder = this.menuRepository
      .createQueryBuilder("menu")
      .select("menu.menu_id", "menu_id")
      .addSelect("menu.menu_name", "menu_name")
      // .addSelect("menu.menu_type", "menu_type")
      .addSelect("ifnull(menu.parentMenuId,0)", "parentId");
    // .andWhere("menu.menu_type = 'C' ");
    const menuList = await queryBuilder.groupBy("menu.menu_id").getRawMany();
    const menuTreeList = [];
    this.sharedService.handleTree(menuList, "menu_id").forEach((item) => {
      menuTreeList.push(item);
      // if (item.menu_type == "C") {
      //   menuTreeList.push(item);
      // }
    });
    return this.createMenuTree(menuTreeList);
  }

  createMenuTree(menuArr: Menu[]): MenuTree[] {
    const routerList: MenuTree[] = [];
    menuArr.forEach((item) => {
      const router = new MenuTree();
      router.value = item.menu_id.toString();
      router.label = item.menu_name;
      if (item.children && item.children.length) {
        router.children = this.createMenuTree(item.children);
      }
      routerList.push(router);
    });
    return routerList;
  }

  // 根据 parentId 查询其所有孩子
  async findChildrenByParentId(parentId: string): Promise<Menu[]> {
    return this.menuRepository
      .createQueryBuilder("menu")
      .where("menu.parentmenuId = :parentId", { parentId })
      .getMany();
  }
  // 删除菜单
  async delete(menu_id: string | number) {
    return this.menuRepository.delete(menu_id);
  }

  // 通过id数组查询
  async listByIdArr(menuIdArr: number[]) {
    return this.menuRepository.find({
      where: {
        menu_id: In(menuIdArr),
      },
    });
  }

  // 通过角色id查询菜单
  async getMenusByRoleId(role_id: string | number) {
    return await this.menuRepository
      .createQueryBuilder("menu")
      .select("menu.menu_id", "menu_id")
      .addSelect("menu.menu_name", "menu_name")
      .leftJoin("menu.roles", "role")
      .where("role.role_id = :role_id", { role_id })
      .getRawMany();
  }
}
